#ifndef __WRAPPER_HYPRE_H__
#define __WRAPPER_HYPRE_H__

#define MIN(a, b) (a) < (b) ? (a) : (b)
#ifndef TEST_CNT
#define TEST_CNT 1
#endif

#include "common.h"
#include <string>
class TEST_RECORD {
public:
    double setup = 0.0, solve = 0.0, prec = 0.0;
    int iter = 0;
    bool operator < (const TEST_RECORD & rec) {
        double my_tot = setup + solve;
        double his_tot = rec.setup + rec.solve;
        return my_tot < his_tot;
    }
};

struct TEST_CONFIG
{
    std::string case_name = "null";
    int max_iter = 300;
    double atol = 0.0;// 绝对残差
    double rtol = 1.0e-7;// 相对残差
    int iter_print_level = 2;
    int prec_print_level = 1;
    int restart_len = 10;
};

template<typename idx_t>
class PartDescriptor
{
public:
    idx_t id;// 全局块序号
    idx_t ilower[3], iupper[3];
    idx_t nelems;
};


#include "HYPRE_sstruct_ls.h"
#include "_hypre_sstruct_ls.h"

extern HYPRE_Solver par_solver, par_precond;
extern HYPRE_SStructSolver solver, precond;

void buildup_solver(std::string solver_name, std::string prec_name, const TEST_CONFIG & config_file);
void destroy_solver(std::string solver_name, std::string prec_name);
void setup_and_solve(std::string solver_name, std::string prec_name, void* A, void* b, void* x,
    HYPRE_Real & t_setup, HYPRE_Real & t_solve, HYPRE_Real & final_res_norm, HYPRE_Int & num_iterations);

void check_residual(std::string prec_name, const HYPRE_SStructMatrix ss_A, const HYPRE_SStructVector ss_x,
    const HYPRE_SStructVector ss_b, HYPRE_SStructVector ss_y, HYPRE_Real & r_nrm2, HYPRE_Real & b_nrm2);
// void check_residual(std::string prec_name,
//     void* A, void* x, void* b, void* y, HYPRE_Real & r_nrm2, HYPRE_Real & b_nrm2);

void stat_amg_pattern(std::string prec_name);

#endif